home *** CD-ROM | disk | FTP | other *** search
- /*
- proto.c
-
- converted to Mac FKEY by Alex D. Chaffee (adc)
- (chaffee@reed.bitnet, AOL:AlexCh, CIS:71210,1117)
- Copyright © 1991 Alex Chaffee. Permission granted to change and
- distribute freely, provided all changes are documented.
-
- Version History:
-
- 1.0 3/1/91 Converted mkptypes.c
-
- 1.1 3/9/91 Works with Think C methods and (presumably) C++
- */
-
- /* mkptypes.c comments: */
- /*
- * Program to extract function declarations from C source code
- *
- * Written by Eric R. Smith (ersmith@uwovax.uwo.ca or @uwovax.bitnet)
- * and placed in the public domain
- * Thanks to:
- * Jwahar R. Bammi, for catching several bugs and providing the Unix makefiles
- * Byron T. Jenings Jr. for cleaning up the space code, providing a Unix
- * manual page, and some ANSI and C++ improvements.
- * Skip Gilbrech for code to skip parameter names in prototypes.
- * ... and many others for helpful comments and suggestions.
- */
-
- /*
- UNIX command-line options - compiled in.
- To effect any of these options, either comment or uncomment the
- #defines and recompile. Some of them have not been fully tested,
- so be careful.
- */
-
- /* #define opt_e /**/
- /* The -e option causes the "extern" keyword to be explicitly printed for
- external functions. Some non-ANSI compilers may need this.
- */
-
- /* #define opt_n /**/
- /* The -n option causes the line number where each function was defined to
- be prepended to the prototype declaration as a comment.
- */
-
- #define macro_name_string "_P"
- /* This option controls the name of the macro used to guard prototype
- definitions. Normally this is "_P", but you can change it to any string
- you like. To eliminate the guard macro entirely, use the -A option.
- (Formerly -p option -adc)
- */
-
- #define opt_s /**/
- /* The -s option causes prototypes to be generated for functions declared
- "static" as well as extern functions.
- */
-
- /* #define opt_x /**/
- /* The -x option causes parameter names to be omitted from the output proto-
- types. This may be necessary for some brain-damaged pseudo-ANSI com-
- pilers. You may also prefer this style of output. This option has not been
- thoroughly tested.
- */
-
- /* #define opt_z /**/
- /* The -z option suppresses the definition of the prototype macro given by -p.
- Header files generated by mkptypes with this option will not work unless
- the prototype macro has been defined elsewhere in the program by the user.
- Used with the -p option, the -z option allows use of predefined prototype
- hiding macros that may exist on some systems.
- */
-
- #define opt_A /**/
- /* The -A option causes the prototypes emitted to be only readable by ANSI
- compilers. Normally, the prototypes are "macro-ized" so that compilers
- with __STDC__not defined don't see them.
- */
-
- #define opt_C /**/
- /* This option causes Think C class names to be placed in comments following
- the method prototype. e.g.
- void amethodname(int x); /* aclassname * /
- -adc
- */
-
- /* #define opt_H /**/
- /* This option prints a header ("/* Prototypes * /") at the top of the
- prototype list -adc
- */
-
- #include <stddef.h>
- #include <stdlib.h>
-
- #ifndef EXIT_SUCCESS
- #define EXIT_SUCCESS 0
- #define EXIT_FAILURE 1
- #endif
-
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
-
- #include "config.h"
- #include "hfile.h"
- #include "proto.h"
-
- /*#define DEBUG(s) (fputs(s, stderr)) /* */
- #define DEBUG(s) /* */
-
- #define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_'))
- #define ABORTED ( (Word *) -1 )
- #define MAXPARAM 20 /* max. number of parameters to a function */
- #define NEWBUFSIZ (20480*sizeof(char)) /* new buffer size */
-
- int dostatic = 0; /* do static functions? */
- int donum = 0; /* print line numbers? */
- int define_macro = 1; /* define macro for prototypes? */
- int use_macro = 1; /* use a macro for prototypes? */
- char macro_name[sizeof(macro_name_string)+1]; /* macro to use for prototypes */
- int no_parm_names = 0; /* no parm names - only types */
- int print_extern = 0; /* use "extern" before function declarations */
- #ifdef CPP
- int call_cpp = 0; /* preprocess files */
- #endif
- int print_class = 0; /* show class name -adc */
-
- int inquote = 0; /* in a quote?? */
- int newline_seen = 1; /* are we at the start of a line */
- long linenum = 1L; /* line number in current file */
- int glastc = ' '; /* last char. seen by getsym() */
-
- static char *typewords[15];
-
- typedef struct word {
- struct word *next;
- char string[1];
- } Word;
-
-
- /* Local Prototypes */
- #pragma mark prototypes
- Word *word_alloc(char *s);
- void word_free(Word *w);
- int List_len(Word *w);
- Word *word_append(Word *w1, Word *w2);
- int foundin(Word *w1, Word *w2);
- void addword(Word *w, char *s);
- void typefixhack(Word *w);
- int ngetc(HFILE *h);
- int hnextch(HFILE *h);
- int nextch(HFILE *h);
- int getsym(char *buf, HFILE *h);
- int skipit(char *buf, HFILE *h);
- int is_type_word(char *s);
- Word *typelist(Word *p);
- Word *getparamlist(HFILE *h);
- void emit(HFILE *hOut, Word *wlist, Word *plist, long startline);
- void getdecl(HFILE *h, HFILE *hOut);
- void buildtypewords(void);
-
- /*
- * Routines for manipulating lists of words.
- */
-
- Word *word_alloc(s)
- char *s;
- {
- Word *w;
-
- /* note that sizeof(Word) already contains space for a terminating null
- * however, we add 1 so that typefixhack can promote "float" to "double"
- * by just doing a strcpy.
- */
- w = (Word *) malloc(sizeof(Word) + strlen(s) + 1);
- strcpy(w->string, s);
- w->next = NULL;
- return w;
- }
-
- void word_free(w)
- Word *w;
- {
- Word *oldw;
- while (w) {
- oldw = w;
- w = w->next;
- free(oldw);
- }
- }
-
- /* return the length of a list; empty words are not counted */
- int
- List_len(w)
- Word *w;
- {
- int count = 0;
-
- while (w) {
- if (*w->string) count++;
- w = w->next;
- }
- return count;
- }
-
- /* Append two lists, and return the result */
-
- Word *word_append(w1, w2)
- Word *w1, *w2;
- {
- Word *r, *w;
-
- r = w = word_alloc("");
-
- while (w1) {
- w->next = word_alloc(w1->string);
- w = w->next;
- w1 = w1->next;
- }
- while (w2) {
- w->next = word_alloc(w2->string);
- w = w->next;
- w2 = w2->next;
- }
-
- return r;
- }
-
- /* see if the last entry in w2 is in w1 */
-
- int
- foundin(w1, w2)
- Word *w1, *w2;
- {
- while (w2->next)
- w2 = w2->next;
-
- while (w1) {
- if (!strcmp(w1->string, w2->string))
- return 1;
- w1 = w1->next;
- }
- return 0;
- }
-
- /* add the string s to the given list of words */
-
- void addword(w, s)
- Word *w; char *s;
- {
- while (w->next) w = w->next;
- w->next = word_alloc(s);
- }
-
- /* typefixhack: promote formal parameters of type "char", "unsigned char",
- "short", or "unsigned short" to "int".
- */
-
- void typefixhack(w)
- Word *w;
- {
- Word *oldw = 0;
-
- while (w) {
- if (*w->string) {
- if ( (!strcmp(w->string, "char") ||
- !strcmp(w->string, "short") )
- && (List_len(w->next) < 2) )
- {
- /* delete any "unsigned" specifier present -- yes, it's supposed to do this */
- if (oldw && !strcmp(oldw->string, "unsigned")) {
- oldw->next = w->next;
- free(w);
- w = oldw;
- }
- strcpy(w->string, "int");
- }
- else if ( !strcmp(w->string, "float") &&
- List_len(w->next) < 2 )
- {
- strcpy(w->string, "double");
- }
- }
- w = w->next;
- }
- }
-
- /* read a character: if it's a newline, increment the line count */
-
- #ifdef __GNUC__ /* ++jrb */
- inline
- #endif
- int ngetc(h)
- HFILE *h;
- {
- register int c;
-
- c = hgetc(h);
- if (c == '\n') linenum++;
-
- return c;
- }
-
- /* read the next character from the file. If the character is '\' then
- * read and skip the next character. Any comment sequence is converted
- * to a blank.
- */
-
- int hnextch(h)
- HFILE *h;
- {
- int c, lastc, incomment;
-
- c = ngetc(h);
- while (c == '\\') {
- DEBUG("hnextch: in backslash loop\n");
- c = ngetc(h); /* skip a character */
- c = ngetc(h);
- }
- if (c == '/' && !inquote) {
- c = ngetc(h);
- if (c == '*') {
- incomment = 1;
- c = ' ';
- DEBUG("hnextch: comment seen\n");
- while (incomment) {
- lastc = c;
- c = ngetc(h);
- if (lastc == '*' && c == '/')
- incomment = 0;
- else if (c < 0)
- return c;
- }
- return hnextch(h);
- }
- else {
- /* if we pre-fetched a linefeed, remember to adjust the line number */
- if (c == '\n') linenum--;
- hungetc(c, h);
- return '/';
- }
- }
- return c;
- }
-
-
- /* Get the next "interesting" character. Comments are skipped, and strings
- * are converted to "0". Also, if a line starts with "#" it is skipped.
- */
-
- int nextch(h)
- HFILE *h;
- {
- int c, n;
- char *p, numbuf[10];
-
- c = hnextch(h);
-
- /* skip preprocessor directives */
- /* EXCEPTION: #line nnn or #nnn lines are interpreted */
-
- if (newline_seen && c == '#') {
- /* skip blanks */
- do {
- c = hnextch(h);
- } while ( c >= 0 && (c == '\t' || c == ' ') );
- /* check for #line */
- if (c == 'l') {
- c = hnextch(h);
- if (c != 'i') /* not a #line directive */
- goto skip_rest_of_line;
- do {
- c = hnextch(h);
- } while (c >= 0 && c != '\n' && !isdigit(c));
- }
-
- /* if we have a digit it's a line number, from the preprocessor */
- if (c >= 0 && isdigit(c)) {
- p = numbuf;
- for (n = 8; n >= 0; --n) {
- *p++ = c;
- c = hnextch(h);
- if (c <= 0 || !isdigit(c))
- break;
- }
- *p = 0;
- linenum = atol(numbuf) - 1;
- }
-
- /* skip the rest of the line */
- skip_rest_of_line:
- while (c >= 0 && c != '\n')
- c = hnextch(h);
- if (c < 0)
- return c;
- }
- newline_seen = (c == '\n');
-
- if (c == '\'' || c == '\"') {
- DEBUG("nextch: in a quote\n");
- inquote = c;
- while ( (c = hnextch(h)) >= 0 ) {
- if (c == inquote) {
- inquote = 0;
- DEBUG("nextch: out of quote\n");
- return '0';
- }
- }
- DEBUG("nextch: EOF in a quote\n");
- }
- return c;
- }
-
- /*
- * Get the next symbol from the file, skipping blanks.
- * Return 0 if OK, -1 for EOF.
- * Also collapses everything between { and }
- */
-
- int
- getsym(buf, h)
- char *buf; HFILE *h;
- {
- register int c;
- int inbrack = 0;
-
- DEBUG("in getsym\n");
- c = glastc;
- while ((c > 0) && isspace(c)) {
- c = nextch(h);
- }
- DEBUG("getsym: spaces skipped\n");
- if (c < 0) {
- DEBUG("EOF read in getsym\n");
- return -1;
- }
- if (c == '{') {
- inbrack = 1;
- DEBUG("getsym: in bracket\n");
- while (inbrack) {
- c = nextch(h);
- if (c < 0) {
- DEBUG("getsym: EOF seen in bracket loop\n");
- glastc = c;
- return c;
- }
- if (c == '{') inbrack++;
- else if (c == '}') inbrack--;
- }
- strcpy(buf, "{}");
- glastc = nextch(h);
- DEBUG("getsym: out of in bracket loop\n");
- return 0;
- }
- if (!ISCSYM(c)) {
- *buf++ = c;
- *buf = 0;
- glastc = nextch(h);
- DEBUG("getsym: returning special symbol\n");
- return 0;
- }
- while (ISCSYM(c)) {
- *buf++ = c;
- c = nextch(h);
- }
- *buf = 0;
- glastc = c;
- DEBUG("getsym: returning word\n");
- return 0;
- }
-
- /*
- * skipit: skip until a ";" or the end of a function declaration is seen
- */
- int skipit(buf, h)
- char *buf;
- HFILE *h;
- {
- int i;
-
- do {
- DEBUG("in skipit loop\n");
- i = getsym(buf, h);
- if (i < 0) return i;
- } while (*buf != ';' && *buf != '{');
-
- return 0;
- }
-
- /*
- * find most common type specifiers for purpose of ruling them out as
- * parm names
- */
-
- int is_type_word(s)
- char *s;
- {
- #if 0
- static char *typewords[] = {
- "char", "const", "double", "enum",
- "float", "int", "long", "short",
- "signed", "struct", "union", "unsigned",
- "void", "volatile", (char *)0
- };
- #endif
- register char **ss;
-
- for (ss = typewords; *ss; ++ss)
- if (strcmp(s, *ss) == 0)
- return 1;
-
- return 0;
- }
-
-
- /* Ad-hoc macro to recognize parameter name for purposes of removal.
- * Idea is to remove the bulk of easily recognized parm names without
- * losing too many type specifiers. (sg)
- */
- #define IS_PARM_NAME(w) \
- (ISCSYM(*(w)->string) && !is_type_word((w)->string) && \
- (!(w)->next || *(w)->next->string == ',' || \
- *(w)->next->string == '['))
-
-
- /*
- * given a list representing a type and a variable name, extract just
- * the base type, e.g. "struct word *x" would yield "struct word"
- */
-
- Word *typelist(p)
- Word *p;
- {
- Word *w, *r;
-
- r = w = word_alloc("");
- while (p && p->next) {
- /* handle int *x --> int */
- if (p->string[0] && !ISCSYM(p->string[0]))
- break;
- /* handle int x[] --> int */
- if (p->next->string[0] == '[')
- break;
- w->next = word_alloc(p->string);
- w = w->next;
- p = p->next;
- }
- return r;
- }
-
- /*
- * Get a parameter list; when this is called the next symbol in line
- * should be the first thing in the list.
- */
-
- Word *getparamlist(h)
- HFILE *h;
- {
- static Word *pname[MAXPARAM]; /* parameter names */
- Word *tlist, /* type name */
- *plist; /* temporary */
- int np = 0; /* number of parameters */
- int typed[MAXPARAM]; /* parameter has been given a type */
- int tlistdone; /* finished finding the type name */
- int sawsomething;
- int i;
- int inparen = 0;
- char buf[80];
-
- DEBUG("in getparamlist\n");
- for (i = 0; i < MAXPARAM; i++)
- typed[i] = 0;
-
- plist = word_alloc("");
-
- /* first, get the stuff inside brackets (if anything) */
-
- sawsomething = 0; /* gets set nonzero when we see an arg */
- for (;;) {
- if (getsym(buf, h) < 0) return NULL;
- if (*buf == ')' && (--inparen < 0)) {
- if (sawsomething) { /* if we've seen an arg */
- pname[np] = plist;
- plist = word_alloc("");
- np++;
- }
- break;
- }
- if (*buf == ';') { /* something weird */
- return ABORTED;
- }
- sawsomething = 1; /* there's something in the arg. list */
- if (*buf == ',' && inparen == 0) {
- pname[np] = plist;
- plist = word_alloc("");
- np++;
- }
- else {
- addword(plist, buf);
- if (*buf == '(') inparen++;
- }
- }
-
- /* next, get the declarations after the function header */
-
- inparen = 0;
-
- tlist = word_alloc("");
- plist = word_alloc("");
- tlistdone = 0;
- sawsomething = 0;
- for(;;) {
- if (getsym(buf, h) < 0) return NULL;
-
- /* handle a list like "int x,y,z" */
- if (*buf == ',' && !inparen) {
- if (!sawsomething)
- return NULL;
- for (i = 0; i < np; i++) {
- if (!typed[i] && foundin(plist, pname[i])) {
- typed[i] = 1;
- word_free(pname[i]);
- pname[i] = word_append(tlist, plist);
- /* promote types */
- typefixhack(pname[i]);
- break;
- }
- }
- if (!tlistdone) {
- tlist = typelist(plist);
- tlistdone = 1;
- }
- word_free(plist);
- plist = word_alloc("");
- }
- /* handle the end of a list */
- else if (*buf == ';') {
- if (!sawsomething)
- return ABORTED;
- for (i = 0; i < np; i++) {
- if (!typed[i] && foundin(plist, pname[i])) {
- typed[i] = 1;
- word_free(pname[i]);
- pname[i] = word_append(tlist, plist);
- typefixhack(pname[i]);
- break;
- }
- }
- tlistdone = 0;
- word_free(tlist); word_free(plist);
- tlist = word_alloc("");
- plist = word_alloc("");
- }
- /* handle the beginning of the function */
- else if (!strcmp(buf, "{}")) break;
- /* otherwise, throw the word into the list (except for "register") */
- else if (strcmp(buf, "register")) {
- sawsomething = 1;
- addword(plist, buf);
- if (*buf == '(') inparen++;
- if (*buf == ')') inparen--;
- }
- }
-
- /* Now take the info we have and build a prototype list */
-
- /* empty parameter list means "void" */
- if (np == 0)
- return word_alloc("void");
-
- plist = tlist = word_alloc("");
- for (i = 0; i < np; i++) {
-
- /* If no type provided, make it an "int" */
- if ( !(pname[i]->next) ||
- (!(pname[i]->next->next)&&strcmp(pname[i]->next->string, "void"))) {
- addword(tlist, "int");
- }
- while (tlist->next) tlist = tlist->next;
- tlist->next = pname[i];
- if (i < np - 1)
- addword(tlist, ",");
- }
- return plist;
- }
-
- /*
- * emit a function declaration. The attributes and name of the function
- * are in wlist; the parameters are in plist.
- */
-
- void emit(hOut, wlist, plist, startline)
- HFILE *hOut;
- Word *wlist, *plist;
- long startline;
- {
- Word *w;
- int count = 0;
- int needspace = 0;
- int isstatic = 0;
- Word *class = 0L; /* class name */
- Word **lastnext; /* pointer to previous word's next field */
-
- DEBUG("emit called\n");
- if (donum)
- hprintf(hOut,"/*%8ld */ ", startline);
-
- for (w = wlist; w; w = w->next) {
- if (w->string[0]) {
- count ++;
- if (!strcmp(w->string, "static"))
- isstatic = 1;
- }
- }
-
- /* if the -e flag was given, and it's not a static function, print "extern" */
-
- if (print_extern && !isstatic) {
- hprintf(hOut,"extern ");
- }
-
- if (count < 2) {
- hprintf(hOut,"int");
- needspace = 1;
- }
-
- /* TCL definitions come out as "class" ":" ":" "func" */
- /* Here we strip the ":"s, save the class name for later, and retie
- the linked list -adc */
-
- w = wlist;
- if (w->next) /* don't worry about single names */
- {
- lastnext = &wlist;
- while (w->next && *(w->next->string) != ':')
- {
- lastnext = &((*lastnext)->next);
- w = w->next;
- }
- if (*(w->next->string) == ':' && w->next->next)
- if (*(w->next->next->string) == ':' && w->next->next->next)
- {
- class = w; /* save class name */
- *lastnext = w->next->next->next; /* close gap */
- free(w->next->next); /* free memory */
- free(w->next);
- }
- }
-
- /* Scan and print the name list */
- for (w = wlist; w; w = w->next) {
- if (needspace)
- hprintf(hOut," ");
- hprintf(hOut,"%s", w->string);
- needspace = ISCSYM(w->string[0]);
- }
-
- /* Print the '(' */
- if (use_macro)
- hprintf(hOut," %s((", macro_name);
- else
- hprintf(hOut,"(");
- needspace = 0;
-
- /* Print the parameters */
- for (w = plist; w; w = w->next) {
- if (no_parm_names && IS_PARM_NAME(w))
- continue;
- if (w->string[0] == ',')
- needspace = 1;
- else if (w->string[0] == '[')
- needspace = 0;
- else
- {
- if (needspace)
- hprintf(hOut," ");
- needspace = ISCSYM(w->string[0]);
- }
- hprintf(hOut,"%s", w->string);
- }
- if (use_macro)
- hprintf(hOut,"));");
- else
- hprintf(hOut,");");
-
- /* Print the class name - adc 3/9/91 */
- if (class)
- {
- if (print_class)
- hprintf(hOut,"\t/* %s */", class->string);
- free(class);
- }
-
- hprintf(hOut,"\n");
- }
-
- /*
- * get all the function declarations
- */
-
- void getdecl(h, hOut)
- HFILE *h, *hOut;
- {
- Word *plist, *wlist = NULL;
- char buf[80];
- int sawsomething;
- long startline; /* line where declaration started */
- int oktoprint;
- again:
- word_free(wlist);
- wlist = word_alloc("");
- sawsomething = 0;
- oktoprint = 1;
-
- for(;;) {
- DEBUG("main getdecl loop\n");
- if (getsym(buf,h) < 0) {
- DEBUG("EOF in getdecl loop\n");
- return;
- }
- /* try to guess when a declaration is not an external function definition */
- if (!strcmp(buf, ",") || !strcmp(buf, "{}") ||
- !strcmp(buf, "=") || !strcmp(buf, "typedef") ||
- !strcmp(buf, "extern")) {
- skipit(buf, h);
- goto again;
- }
- if (!dostatic && !strcmp(buf, "static")) {
- oktoprint = 0;
- }
- /* for the benefit of compilers that allow "inline" declarations */
- if (!strcmp(buf, "inline") && !sawsomething)
- continue;
- if (!strcmp(buf, ";")) goto again;
-
- /* A left parenthesis *might* indicate a function definition */
- if (!strcmp(buf, "(")) {
- startline = linenum;
- if (!sawsomething || !(plist = getparamlist(h))) {
- skipit(buf, h);
- goto again;
- }
- if (plist == ABORTED)
- goto again;
-
- /* It seems to have been what we wanted */
- if (oktoprint)
- emit(hOut, wlist, plist, startline);
- word_free(plist);
- goto again;
- }
- addword(wlist, buf);
- sawsomething = 1;
- }
- }
-
- /*
- buildtypewords
-
- Think doesn't like strings in globals, so we build the typewords
- array here -adc
- */
- void buildtypewords(void)
- {
- typewords[0] = "char";
- typewords[1] = "const";
- typewords[2] = "double";
- typewords[3] = "enum";
- typewords[4] = "float";
- typewords[5] = "int";
- typewords[6] = "long";
- typewords[7] = "short";
- typewords[8] = "signed";
- typewords[9] = "struct";
- typewords[10] = "union";
- typewords[11] = "unsigned";
- typewords[12] = "void";
- typewords[13] = "volatile";
- typewords[14] = (char *)0;
- }
-
- /*
- proto
-
- interface to mkptypes
-
- given two initialized Mac handles
- */
- int proto (Handle handIn, Handle handOut)
- {
- HFILE *hIn, *hOut;
-
- /* set globals */
- #ifdef opt_e
- print_extern = 1;
- #endif
- #ifdef opt_n
- donum = 1;
- #endif
- #ifdef opt_s
- dostatic = 1;
- #endif
- #ifdef opt_x
- /* no parm names, only types (sg) */
- no_parm_names = 1;
- #endif
- #ifdef opt_z
- define_macro = 0;
- #endif
- #ifdef opt_A
- use_macro = 0;
- #endif
- #ifdef opt_C
- print_class = 1;
- #endif
-
- buildtypewords();
- strcpy(macro_name, macro_name_string);
-
- if (!(hIn = hopen(handIn, "r"))) {
- #ifdef APP
- perror("Can't open input handle");
- #endif
- return(EXIT_FAILURE);
- }
- if (!(hOut = hopen(handOut, "r"))) {
- #ifdef APP
- perror("Can't open output handle");
- #endif
- return(EXIT_FAILURE);
- }
-
- #ifdef opt_H
- hprintf(hOut, "\n/* Prototypes */\n");
- #endif
-
- if (use_macro && define_macro)
- {
- hprintf(hOut, "#if defined(__STDC__) || defined(__cplusplus)\n");
- hprintf(hOut, "# define %s(s) s\n", macro_name);
- hprintf(hOut, "#else\n");
- hprintf(hOut, "# define %s(s) ()\n", macro_name);
- hprintf(hOut, "#endif\n\n");
- }
-
- linenum = 1;
- newline_seen = 1;
- glastc = ' ';
- getdecl(hIn,hOut);
- hclose(hIn);
- hclose(hOut);
-
- if (use_macro && define_macro) {
- hprintf(hOut,"\n#undef %s\n", macro_name); /* clean up namespace */
- }
- return(EXIT_SUCCESS);
- }
-